//
//  wfSocket.m
//  智能控制系统
//
//  Created by Rankin on 15/9/18.
//
//

#import "wfSocket.h"
#import "GCDAsyncSocket.h"
#import "GCDAsyncUdpSocket.h"
#import <arpa/inet.h>

@implementation wfSocket : CDVPlugin
GCDAsyncSocket* tcp;
GCDAsyncSocket* remoteTcp;
GCDAsyncUdpSocket* udp;
NSString *ipRemote;
int portRemote;
NSArray *data;
NSMutableData *readDatas;
NSString *umid;
CDVInvokedUrlCommand *getPilistCmd;
-(void) pluginInitialize {
    tcp = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    remoteTcp = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    tcp.delegate = self;
    remoteTcp.delegate = self;
    udp = [[GCDAsyncUdpSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    readDatas = [[NSMutableData alloc]init];
}

-(void) listenOnPort: (CDVInvokedUrlCommand *) command{
    NSString *type = [command.arguments objectAtIndex:0];
    int port = [[command.arguments objectAtIndex:1]intValue];
    if ([type isEqual: @"tcp"]) {
        
    }
}


-(void) getPiList:(CDVInvokedUrlCommand *) command{
    NSData* helloStr= [@"hello" dataUsingEncoding: NSUTF8StringEncoding];
    NSError *error = nil;
    [udp enableBroadcast:YES error:&error];
    if (error) {
        NSLog(@"开启广播%d失败%@",31500,error);
    }
    [udp sendData:helloStr toHost:@"255.255.255.255" port:31500 withTimeout:-1 tag:1];
    //开始接收数据
    [udp beginReceiving:&error];
    if (error) {
        NSLog(@"开始接收数据失败..%@",error);
    }
    getPilistCmd = command;

    
//        [udp close];
}



-(void) sendData:(GCDAsyncSocket *) socket{
    char *sendDatas = malloc(data.count*sizeof(sendDatas));
    for (int i=0; i<data.count; i++) {
        sendDatas[i] = [[data objectAtIndex:i]intValue];
    }
    NSData* myData = [NSData dataWithBytes:sendDatas length:data.count];
    [socket writeData:myData withTimeout:-1 tag:0];
}


-(void)connect:(CDVInvokedUrlCommand *)command  {
    NSString *type = [command.arguments objectAtIndex:0];
    NSString *ip = [command.arguments objectAtIndex:1];
    int port = [[command.arguments objectAtIndex:2]intValue];
    data = [command.arguments objectAtIndex:3];
    ipRemote = [command.arguments objectAtIndex:4];
    portRemote = [[command.arguments objectAtIndex:5]intValue];
    umid = [command.arguments objectAtIndex:6];
    NSError *err = nil;
    if ([type isEqual: @"tcp"]) {
        if ([tcp isConnected] || [remoteTcp isConnected]) {
            if ([tcp isConnected]) {
                [self sendData:tcp];
            }else{
                [self sendData:remoteTcp];
            }
        }
        else{
            BOOL connState=[tcp connectToHost:ip onPort:port withTimeout:3 error:&err];
            if(!connState){
                NSLog(@"建立链接：%@ 失败 %@",ip,err);
            }else{
                NSLog(@"建立链接：%@ 成功",ip);
            }
        }
    }else{
        
    }
    
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    NSLog(@"host: %@", host);
    if ([host isEqual: @"192.168.0.80"]) {
        [self sendData:tcp];
        [tcp readDataWithTimeout:-1 tag:0];

    }else{
        [self sendData:remoteTcp];
        [remoteTcp readDataWithTimeout:-1 tag:0];

    }
    }

-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    if (err) {
        NSLog(@"连接失败");
        BOOL connState=[remoteTcp connectToHost:ipRemote onPort:portRemote withTimeout:3 error:&err];
        if(!connState){
            NSLog(@"建立链接：%@ 失败",err);
        }else{
            NSLog(@"建立链接：%@ 成功",ipRemote);
            NSData* appStr= [@"app" dataUsingEncoding: NSUTF8StringEncoding];
            [remoteTcp writeData:appStr withTimeout:-1 tag:0];
            [NSThread sleepForTimeInterval:0.5f];
            NSData* umidStr= [umid dataUsingEncoding: NSUTF8StringEncoding];
            [remoteTcp writeData:umidStr withTimeout:-1 tag:0];
            [NSThread sleepForTimeInterval:0.5f];
        }
        
    }else{
        NSLog(@"正常断开");
    }
}

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext{
    NSString *umid = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    struct sockaddr_in *addr = (struct sockaddr_in *)[address bytes];
    NSString *ip = [NSString stringWithCString:inet_ntoa(addr->sin_addr) encoding:NSASCIIStringEncoding];
    NSDictionary *piData = [NSDictionary dictionaryWithObjectsAndKeys:
                          umid, @"umid",
                          ip, @"ip",
                          nil];
    CDVPluginResult *ret = nil;
    ret = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:piData];
    [self.commandDelegate sendPluginResult:ret callbackId:getPilistCmd.callbackId];
    
}


- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error

{
    
    NSLog(@"udpSocketDidClose Error:%@",[error description]);
    
}

-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

{
    
    NSString *newMessage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    NSLog(@"接收到服务器返回的信息：%@",newMessage);
    @synchronized (readDatas) {
        [readDatas appendData:data];
        //                    NSLog(@"%@",readDatas);
        [self analyseMpProtocol];
    }
    
    [tcp readDataWithTimeout:100 tag:0];
    [remoteTcp readDataWithTimeout:100 tag:0];
    
}



//- (void)recvDatas{
//    dispatch_async(dispatch_get_global_queue(0, 0), ^{
//        while (true) {
//            void *recvDatas = malloc(39126);
//            int length = sizeof(recvDatas);
//            
//            long recvCount = recv(tcp.sockDescriptor,recvDatas,length,0);
//            if(recvCount==-1){
//                //接收数据为-1时表示已经断开了
//                //            [self close];
//                //todo 通知js断线
//                
//                NSLog(@"断线");
//                return ;
//            }
//            recvDatas = realloc(recvDatas, recvCount);
//            //                NSLog(@"recv:%ld%@",recvCount,[NSData dataWithBytes:recvDatas length:recvCount]);
//            if (recvCount>0) {
//                @synchronized (readDatas) {
//                    [readDatas appendBytes:recvDatas length:recvCount];
//                    //                    NSLog(@"%@",readDatas);
//                    [self analyseMpProtocol];
//                }
//            }
//        }
//    });
//}

- (void) sendMessage :(NSString *)host :(int)port :(NSString *)chunk {
    
    // Handling escape chars
    NSMutableString *data = [NSMutableString stringWithString : chunk];
    [data replaceOccurrencesOfString   : @"\n"
                            withString : @"\\n"
                            options    : NSCaseInsensitiveSearch
                            range      : NSMakeRange(0, [data length])];
    
    // Relay to webview
    NSString *receiveHook = [NSString stringWithFormat : @"wfSocket.receiveMsg('%@', %d, '%@', '%@' );",
                             host, port, [NSString stringWithFormat:@"%@:%d",host,port]  , [NSString stringWithString : data]];
    
    
//        [self writeJavascript:receiveHook]; 废弃的方法
    [self.commandDelegate evalJs:receiveHook];
   
    
}


-(void)resetReadData{
    
    if ([readDatas length]==0){
        //已经没有数据的就不再处理
        return;
    }
    
    //移除错误数据
    //判断第一项是否要移除
    Byte check1 = {0x00};
    if ([readDatas length]>=1) {
        [readDatas getBytes:&check1 length:1];
    }else{
        return;
    }
    if(check1!=0xaa){
        NSData *newReadData = [readDatas subdataWithRange:NSMakeRange(1, readDatas.length - 1)];
        readDatas = [[NSMutableData alloc]initWithData:newReadData];
        [self resetReadData];
    }
    else{
        //第一项正确后判断第二项
        Byte check2[] = {0x00,0x00};
        if ([readDatas length]>=2) {
            [readDatas getBytes:&check2 length:2];
        }else{
            return;
        }
        
        if(check2[0]!=0xaa||check2[1]!=0x55){
            NSData *newReadData = [readDatas subdataWithRange:NSMakeRange(2, readDatas.length - 2)];
            readDatas = [[NSMutableData alloc]initWithData:newReadData];
            [self resetReadData];
        }
        else{
            //重新读
            [self analyseMpProtocol];
        }
    }
    NSLog(@"data format err");
}
-(void)analyseMpProtocol{
    
    Byte check1 = {0x00};
    if ([readDatas length]>=1) {
        [readDatas getBytes:&check1 length:1];
    }else{
        return;
    }
    
    if(check1!=0xaa){
        NSLog(@"首位校验失败!丢弃不符合规则部分!");
        [self resetReadData];
        return;
    }
    //        NSLog(@"首位校验成功!");
    
    
    Byte check2 = {0x00};
    NSRange c2;
    c2.length = 1;
    c2.location = 1;
    if ([readDatas length]>=2) {
        [readDatas getBytes:&check2 range:c2];
    }else{
        return;
    }
    
    if (check2 != 0x55) {
        NSLog(@"次位校验失败!丢弃不符合规则部分!");
        [self resetReadData];
        return;
    }
    
    //        NSLog(@"次位校验成功!");
    Byte check3 = {0x00};
    
    if ([readDatas length]>=3) {
        NSRange c3;
        c3.length = 1;
        c3.location = 2;
        [readDatas getBytes:&check3 range:c3];
    }else{
        return;
    }
    
    
    if(check3 != 0x00){
        //            NSLog(@"获取报文长度");
        int sendDataLength = check3+3/*前两位要加上*/;
        if([readDatas length]>=sendDataLength){
            //                NSLog(@"确定后续报文完整性成功");
            
            Byte *mb;
            
            mb = (Byte*)malloc(sendDataLength*sizeof(Byte));
            
            [readDatas getBytes:mb length:sendDataLength];
            
            NSMutableArray *returnArr = [[NSMutableArray alloc]init];
            for (int i=0; i<sendDataLength; i++) {
                [returnArr addObject:[NSString stringWithFormat:@"%d", mb[i]]];
            }
            
            NSString *sendData = [returnArr componentsJoinedByString:@"|"];
            
            //            [delegage sendMessage:[sock connectedHost] :[sock connectedPort] :sendData];
            NSLog(sendData);
            
            [self sendMessage :tcp.connectedHost :tcp.connectedPort :sendData];
            
            
            NSData *newReadData = [readDatas subdataWithRange:NSMakeRange(sendDataLength, readDatas.length - sendDataLength)];
            
            readDatas = [[NSMutableData alloc]initWithData:newReadData];
            
            [self analyseMpProtocol];
        }
        else{
            //                NSLog(@"后续报文未完成接收");
            
            return;
        }
    }
}

@end
